/*
 * @Author: lixu lixu@puchigames.com
 * @Date: 2025-09-18 11:10:00
 * @LastEditors: lixu lixu@puchigames.com
 * @LastEditTime: 2025-09-18 11:10:00
 * @FilePath: /go-helper/ixLog/formatter.go
 * @Description: 日志格式化器实现，支持文本、JSON和自定义格式
 */

package ixLog

import (
	"bytes"
	"encoding/json"
	"fmt"
	"path/filepath"
	"strings"
	"text/template"
	"time"
)

// TextFormatter 文本格式化器
type TextFormatter struct {
	EnableColor    bool
	TimeFormat     string
	EnableCaller   bool
	CustomTemplate string
	template       *template.Template
}

// NewTextFormatter 创建文本格式化器
func NewTextFormatter(enableColor bool, timeFormat string, enableCaller bool, customTemplate string) *TextFormatter {
	formatter := &TextFormatter{
		EnableColor:    enableColor,
		TimeFormat:     timeFormat,
		EnableCaller:   enableCaller,
		CustomTemplate: customTemplate,
	}

	if customTemplate != "" {
		tmpl, err := template.New("log").Parse(customTemplate)
		if err == nil {
			formatter.template = tmpl
		}
	}

	return formatter
}

// Format 格式化日志条目
func (f *TextFormatter) Format(entry *LogEntry) ([]byte, error) {
	var buf bytes.Buffer

	// 使用自定义模板
	if f.template != nil {
		return f.formatWithTemplate(entry)
	}

	// 格式化时间
	timestamp := entry.Timestamp.Format(f.TimeFormat)

	// 格式化级别
	level := entry.Level.String()
	if f.EnableColor {
		level = entry.Level.Color() + level + ColorReset
	}

	// 基础信息
	buf.WriteString(fmt.Sprintf("[%s] %s", timestamp, level))

	// 追踪信息
	if entry.TraceID != "" {
		buf.WriteString(fmt.Sprintf(" [%s", entry.TraceID))
		if entry.SpanID != "" {
			buf.WriteString(fmt.Sprintf(":%s", entry.SpanID))
		}
		buf.WriteString("]")
	}

	// 调用者信息
	if f.EnableCaller && entry.Caller != nil {
		filename := filepath.Base(entry.Caller.File)
		buf.WriteString(fmt.Sprintf(" %s:%d", filename, entry.Caller.Line))
		if entry.Caller.Function != "" {
			funcName := filepath.Base(entry.Caller.Function)
			buf.WriteString(fmt.Sprintf(" %s()", funcName))
		}
	}

	// 消息内容
	buf.WriteString(fmt.Sprintf(" %s", entry.Message))

	// 附加字段
	if len(entry.Fields) > 0 {
		buf.WriteString(" |")
		for key, value := range entry.Fields {
			buf.WriteString(fmt.Sprintf(" %s=%v", key, value))
		}
	}

	// 错误信息
	if entry.Error != nil {
		buf.WriteString(fmt.Sprintf(" | error=%v", entry.Error))
	}

	// 调用栈
	if len(entry.Stack) > 0 {
		buf.WriteString("\nStack trace:")
		for _, frame := range entry.Stack {
			buf.WriteString(fmt.Sprintf("\n  %s", frame))
		}
	}

	buf.WriteString("\n")
	return buf.Bytes(), nil
}

// formatWithTemplate 使用模板格式化
func (f *TextFormatter) formatWithTemplate(entry *LogEntry) ([]byte, error) {
	var buf bytes.Buffer

	data := map[string]interface{}{
		"Timestamp":    entry.Timestamp.Format(f.TimeFormat),
		"Level":        entry.Level.String(),
		"Message":      entry.Message,
		"TraceID":      entry.TraceID,
		"SpanID":       entry.SpanID,
		"ParentSpanID": entry.ParentSpanID,
		"Fields":       entry.Fields,
		"Error":        entry.Error,
		"Stack":        entry.Stack,
	}

	if entry.Caller != nil {
		data["Caller"] = map[string]interface{}{
			"File":     filepath.Base(entry.Caller.File),
			"Line":     entry.Caller.Line,
			"Function": filepath.Base(entry.Caller.Function),
		}
	}

	if err := f.template.Execute(&buf, data); err != nil {
		return nil, fmt.Errorf("模板执行失败: %w", err)
	}

	return buf.Bytes(), nil
}

// JSONFormatter JSON格式化器
type JSONFormatter struct {
	TimeFormat   string
	EnableCaller bool
	PrettyPrint  bool
}

// NewJSONFormatter 创建JSON格式化器
func NewJSONFormatter(timeFormat string, enableCaller bool, prettyPrint bool) *JSONFormatter {
	return &JSONFormatter{
		TimeFormat:   timeFormat,
		EnableCaller: enableCaller,
		PrettyPrint:  prettyPrint,
	}
}

// Format 格式化日志条目
func (f *JSONFormatter) Format(entry *LogEntry) ([]byte, error) {
	// 构建JSON数据
	data := map[string]interface{}{
		"timestamp": entry.Timestamp.Format(f.TimeFormat),
		"level":     entry.Level.String(),
		"message":   entry.Message,
	}

	// 追踪信息
	if entry.TraceID != "" {
		data["trace_id"] = entry.TraceID
	}
	if entry.SpanID != "" {
		data["span_id"] = entry.SpanID
	}
	if entry.ParentSpanID != "" {
		data["parent_span_id"] = entry.ParentSpanID
	}

	// 调用者信息
	if f.EnableCaller && entry.Caller != nil {
		data["caller"] = map[string]interface{}{
			"file":     entry.Caller.File,
			"line":     entry.Caller.Line,
			"function": entry.Caller.Function,
		}
	}

	// 附加字段
	if len(entry.Fields) > 0 {
		for key, value := range entry.Fields {
			data[key] = value
		}
	}

	// 错误信息
	if entry.Error != nil {
		data["error"] = entry.Error.Error()
	}

	// 调用栈
	if len(entry.Stack) > 0 {
		data["stack"] = entry.Stack
	}

	// 序列化
	var result []byte
	var err error

	if f.PrettyPrint {
		result, err = json.MarshalIndent(data, "", "  ")
	} else {
		result, err = json.Marshal(data)
	}

	if err != nil {
		return nil, fmt.Errorf("JSON序列化失败: %w", err)
	}

	// 添加换行符
	result = append(result, '\n')
	return result, nil
}

// CustomFormatter 自定义格式化器
type CustomFormatter struct {
	FormatFunc func(*LogEntry) ([]byte, error)
}

// NewCustomFormatter 创建自定义格式化器
func NewCustomFormatter(formatFunc func(*LogEntry) ([]byte, error)) *CustomFormatter {
	return &CustomFormatter{
		FormatFunc: formatFunc,
	}
}

// Format 格式化日志条目
func (f *CustomFormatter) Format(entry *LogEntry) ([]byte, error) {
	if f.FormatFunc == nil {
		return nil, fmt.Errorf("自定义格式化函数不能为空")
	}
	return f.FormatFunc(entry)
}

// LogfmtFormatter logfmt格式化器
type LogfmtFormatter struct {
	TimeFormat   string
	EnableCaller bool
}

// NewLogfmtFormatter 创建logfmt格式化器
func NewLogfmtFormatter(timeFormat string, enableCaller bool) *LogfmtFormatter {
	return &LogfmtFormatter{
		TimeFormat:   timeFormat,
		EnableCaller: enableCaller,
	}
}

// Format 格式化日志条目
func (f *LogfmtFormatter) Format(entry *LogEntry) ([]byte, error) {
	var buf bytes.Buffer

	// 时间戳
	buf.WriteString(fmt.Sprintf("time=%s", entry.Timestamp.Format(f.TimeFormat)))

	// 级别
	buf.WriteString(fmt.Sprintf(" level=%s", entry.Level.String()))

	// 消息
	buf.WriteString(fmt.Sprintf(" msg=%q", entry.Message))

	// 追踪信息
	if entry.TraceID != "" {
		buf.WriteString(fmt.Sprintf(" trace_id=%s", entry.TraceID))
	}
	if entry.SpanID != "" {
		buf.WriteString(fmt.Sprintf(" span_id=%s", entry.SpanID))
	}
	if entry.ParentSpanID != "" {
		buf.WriteString(fmt.Sprintf(" parent_span_id=%s", entry.ParentSpanID))
	}

	// 调用者信息
	if f.EnableCaller && entry.Caller != nil {
		buf.WriteString(fmt.Sprintf(" file=%s", filepath.Base(entry.Caller.File)))
		buf.WriteString(fmt.Sprintf(" line=%d", entry.Caller.Line))
		if entry.Caller.Function != "" {
			buf.WriteString(fmt.Sprintf(" func=%s", filepath.Base(entry.Caller.Function)))
		}
	}

	// 附加字段
	for key, value := range entry.Fields {
		buf.WriteString(fmt.Sprintf(" %s=%v", key, formatLogfmtValue(value)))
	}

	// 错误信息
	if entry.Error != nil {
		buf.WriteString(fmt.Sprintf(" error=%q", entry.Error.Error()))
	}

	buf.WriteString("\n")
	return buf.Bytes(), nil
}

// formatLogfmtValue 格式化logfmt值
func formatLogfmtValue(value interface{}) string {
	switch v := value.(type) {
	case string:
		if strings.ContainsAny(v, " \t\n\r\"") {
			return fmt.Sprintf("%q", v)
		}
		return v
	case time.Time:
		return v.Format(time.RFC3339)
	default:
		str := fmt.Sprintf("%v", v)
		if strings.ContainsAny(str, " \t\n\r\"") {
			return fmt.Sprintf("%q", str)
		}
		return str
	}
}

// GetFormatter 根据配置获取格式化器
func GetFormatter(config *Config) Formatter {
	switch config.Format {
	case TextFormat:
		return NewTextFormatter(
			config.EnableColor,
			config.TimeFormat,
			config.EnableCaller,
			config.CustomTemplate,
		)
	case JSONFormat:
		return NewJSONFormatter(
			config.TimeFormat,
			config.EnableCaller,
			false, // 生产环境不使用pretty print
		)
	case CustomFormat:
		if config.CustomTemplate != "" {
			return NewTextFormatter(
				config.EnableColor,
				config.TimeFormat,
				config.EnableCaller,
				config.CustomTemplate,
			)
		}
		// 如果没有自定义模板，回退到文本格式
		return NewTextFormatter(
			config.EnableColor,
			config.TimeFormat,
			config.EnableCaller,
			"",
		)
	default:
		return NewTextFormatter(
			config.EnableColor,
			config.TimeFormat,
			config.EnableCaller,
			"",
		)
	}
}

// 预定义模板
var (
	// SimpleTemplate 简单模板
	SimpleTemplate = "{{.Timestamp}} [{{.Level}}] {{.Message}}"

	// DetailedTemplate 详细模板
	DetailedTemplate = "{{.Timestamp}} [{{.Level}}] {{if .TraceID}}[{{.TraceID}}] {{end}}{{if .Caller}}{{.Caller.File}}:{{.Caller.Line}} {{end}}{{.Message}}{{if .Fields}} | {{range $k, $v := .Fields}}{{$k}}={{$v}} {{end}}{{end}}"

	// CompactTemplate 紧凑模板
	CompactTemplate = "{{.Timestamp}} {{.Level}} {{.Message}}"

	// TraceTemplate 追踪模板
	TraceTemplate = "{{.Timestamp}} [{{.Level}}] [{{.TraceID}}:{{.SpanID}}] {{.Message}}"
)
